package com.sugar.follow.up.module.business.util.wechat;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.sugar.follow.up.framework.common.exception.ServiceException;
import com.sugar.follow.up.module.business.util.wechat.dto.WeChatAccessTokenDTO;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.Map;

import static com.sugar.follow.up.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.sugar.follow.up.module.business.enums.ErrorCodeConstants.WE_CHAT_GET_WECHAT_OPENID_ERROR;
import static com.sugar.follow.up.module.business.enums.ErrorCodeConstants.WE_CHAT_LOGIN_NOT_RESP;

/**
 * @author Y.sugar
 * @since 2024/5/10 11:27
 */
@Slf4j
public class GongZhongUtil {

    /**
     * 获取AccessToken地址
     */
    private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";

    /**
     * 获取用户信息
     */
    private static final String GET_USER_INFO = "https://api.weixin.qq.com/cgi-bin/user/info?access_token={}&openid={}";

    // 公众号 appId
    private static final String APP_ID = "wx336524726f33d31c";
    // 公众号 appSecret
    private static final String SECRET = "c4791f7b6202dc366dde8b349c2190e9";

    private static final WeChatAccessTokenDTO ACCESS_TOKEN = new WeChatAccessTokenDTO();

    public static String getAccessToken() {
        LocalDateTime nowDateTime = LocalDateTime.now();

        String accessToken = ACCESS_TOKEN.getAccessToken();
        if (StrUtil.isNotBlank(accessToken)) {
            Long expiresIn = ACCESS_TOKEN.getExpiresIn();
            LocalDateTime getDateTime = ACCESS_TOKEN.getGetDateTime();
            if (Math.abs(getDateTime.until(nowDateTime, ChronoUnit.SECONDS)) < expiresIn) {
                return accessToken;
            }
        }

        Map<String, Object> params = new HashMap<>();
        // 小程序 appId
        params.put("appid", APP_ID);
        // 小程序 appSecret
        params.put("secret", SECRET);
        // 授权类型，此处只需填写 client_credential
        params.put("grant_type", "client_credential");

        try {
            String respResStr = HttpUtil.get(ACCESS_TOKEN_URL, params);
            if (StrUtil.isBlank(respResStr)) {
                log.error("请求微信认证接口返回结果为空：{}", respResStr);
                throw exception(WE_CHAT_LOGIN_NOT_RESP);
            }

            // 转为Json对象
            JSONObject respResJson = JSONUtil.parseObj(respResStr);
            // 获取错误码
            accessToken = respResJson.getStr("access_token");
            if (StrUtil.isNotBlank(accessToken)) {
                ACCESS_TOKEN.setAccessToken(accessToken).setExpiresIn(respResJson.getLong("expires_in"))
                        .setGetDateTime(nowDateTime);

                return accessToken;
            } else {
                log.error("请求微信认证接口失败：{}", respResJson.getStr("errmsg"));
                //throw new ServiceException(respResJson.getInt("errcode"), respResJson.getStr("errmsg"));
                throw exception(WE_CHAT_GET_WECHAT_OPENID_ERROR);
            }
        } catch (ServiceException e) {
            throw e;
        } catch (Exception e) {
            log.error("获取微信Token失败：", e);
            throw new ServiceException(500, e.getMessage());
        }
    }

    /**
     * 获取用户手机号
     *
     * @param openid 手机号获取凭证
     * @return 用户手机号
     */
    public static String getUserInfo(String openid) {
        String accessToken = getAccessToken();

        try {
            String respStr = HttpUtil.get(StrUtil.format(GET_USER_INFO, accessToken, openid));
            if (StrUtil.isBlank(respStr)) {
                log.error("请求微信认证接口返回结果为空");
                throw exception(WE_CHAT_LOGIN_NOT_RESP);
            }

            log.info("获取公众号信息：{}", respStr);

            // 转为Json对象
            JSONObject respResJson = JSONUtil.parseObj(respStr);

            return respResJson.getStr("unionid");
        } catch (ServiceException e) {
            throw new ServiceException(e.getCode(), e.getMessage());
        } catch (Exception e) {
            log.error("获取用户信息失败：", e);
            throw new ServiceException(500, e.getMessage());
        }
    }
}
